home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / zprot.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  32KB  |  1,138 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:`
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4. /*
  5.  
  6. #ifndef lint
  7. static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/zprot.c,v 1.4 92/02/12 13:59:51 jonathan Exp $";
  8. #endif
  9.  
  10. /* Change log:
  11.  * $Log:    zprot.c,v $
  12.  * Revision 1.4  92/02/12  13:59:51  jonathan
  13.  * Added "$Log" so RCS will put the log message in the header
  14.  * 
  15.  * 
  16.   
  17.    3.26.90    Harry Morris, morris@think.com
  18.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  19.    4.11.90  HWM - generalized conditional includes (see c-dialect.h)
  20. */
  21.  
  22. #define _C_Z39_50_
  23.  
  24. #include "zprot.h"
  25.  
  26. #include "zutil.h"
  27. #include "cutil.h"
  28. #include <string.h>
  29.  
  30. #ifndef ANSI_LIKE
  31. #include "ustubs.h"
  32. #endif
  33.  
  34. #define RESERVE_SPACE_FOR_HEADER(spaceLeft)        \
  35.     *spaceLeft -= HEADER_LEN;
  36.     
  37. #define RELEASE_HEADER_SPACE(spaceLeft)            \
  38.     if (*spaceLeft > 0)                            \
  39.       *spaceLeft += HEADER_LEN;
  40.     
  41. /*----------------------------------------------------------------------*/
  42.  
  43. InitAPDU* 
  44. makeInitAPDU(search,
  45.          present,
  46.          deleteIt,
  47.          accessControl,
  48.          resourceControl,
  49.          prefSize,
  50.          maxMsgSize,
  51.          auth,
  52.          id,
  53.          name,
  54.          version,
  55.          refID,
  56.          userInfo)
  57. boolean search;
  58. boolean present;
  59. boolean deleteIt;
  60. boolean accessControl;
  61. boolean resourceControl;
  62. long prefSize;
  63. long maxMsgSize;
  64. char* auth;
  65. char* id;
  66. char* name;
  67. char* version;
  68. any* refID;
  69. void* userInfo;
  70.  
  71. /* build an init APDU with user specified information */
  72.   InitAPDU* init = (InitAPDU*)s_malloc((size_t)sizeof(InitAPDU));
  73.  
  74.   init->PDUType = initAPDU;
  75.   init->willSearch = search;
  76.   init->willPresent = present;
  77.   init->willDelete = deleteIt;
  78.   init->supportAccessControl = accessControl;
  79.   init->supportResourceControl = resourceControl;
  80.   init->PreferredMessageSize = prefSize;
  81.   init->MaximumRecordSize = maxMsgSize;
  82.   init->IDAuthentication = s_strdup(auth);
  83.   init->ImplementationID = s_strdup(id);
  84.   init->ImplementationName = s_strdup(name);
  85.   init->ImplementationVersion = s_strdup(version);
  86.   init->ReferenceID = duplicateAny(refID);
  87.   init->UserInformationField = userInfo; /* not copied */
  88.   
  89.   return(init);
  90. }
  91.  
  92. /*----------------------------------------------------------------------*/
  93.  
  94. void 
  95. freeInitAPDU(init)
  96. InitAPDU* init;
  97. /* free an initAPDU */
  98. {
  99.   s_free(init->IDAuthentication);
  100.   s_free(init->ImplementationID);
  101.   s_free(init->ImplementationName);
  102.   s_free(init->ImplementationVersion);
  103.   freeAny(init->ReferenceID);
  104.   s_free(init);
  105. }
  106.  
  107. /*----------------------------------------------------------------------*/
  108.  
  109. char* 
  110. writeInitAPDU(init,buffer,len)
  111. InitAPDU* init;
  112. char* buffer;
  113. long* len;
  114. /* write the init to a buffer, adding system information */
  115. {
  116.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  117.   long size;
  118.   bit_map* optionsBM = NULL;
  119.  
  120.   RESERVE_SPACE_FOR_HEADER(len);
  121.   
  122.   buf = writePDUType(init->PDUType,buf,len);
  123.   
  124.   buf = writeProtocolVersion(buf,len);
  125.   
  126.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  127.                          init->willDelete,init->supportAccessControl,
  128.                          init->supportResourceControl);
  129.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  130.   freeBitMap(optionsBM);
  131.  
  132.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  133.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  134.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  135.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  136.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  137.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  138.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  139.   
  140.   /* go back and write the header-length-indicator */
  141.   RELEASE_HEADER_SPACE(len);
  142.   size = buf - buffer - HEADER_LEN; 
  143.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  144.  
  145.   if (init->UserInformationField != NULL)
  146.     buf = writeInitInfo(init,buf,len);   
  147.     
  148.   return(buf); 
  149. }
  150.  
  151. /*----------------------------------------------------------------------*/
  152.  
  153. char* 
  154. readInitAPDU(init,buffer)
  155. InitAPDU** init;
  156. char* buffer;
  157. {
  158.   char* buf = buffer;
  159.   boolean search,present,delete,accessControl,resourceControl;
  160.   long prefSize,maxMsgSize;
  161.   char *auth,*id,*name,*version;
  162.   long size; 
  163.   pdu_type pduType;
  164.   bit_map* versionBM = NULL;
  165.   bit_map* optionsBM = NULL;
  166.   any *refID = NULL;
  167.   void* userInfo = NULL;
  168.   
  169.   auth = id = name = version = NULL;
  170.   
  171.   /* read required part */
  172.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  173.   buf = readPDUType(&pduType,buf);
  174.   buf = readBitMap(&versionBM,buf); 
  175.   buf = readBitMap(&optionsBM,buf);
  176.   buf = readNum(&prefSize,buf);
  177.   buf = readNum(&maxMsgSize,buf);
  178.   
  179.   /* decode optionsBM */
  180.   search = bitAtPos(0L,optionsBM);
  181.   present = bitAtPos(1L,optionsBM);
  182.   delete = bitAtPos(2L,optionsBM);
  183.   accessControl = bitAtPos(3L,optionsBM);
  184.   resourceControl = bitAtPos(4L,optionsBM);
  185.   
  186.   /* read optional part */
  187.   while (buf < (buffer + size + HEADER_LEN)) 
  188.     { data_tag tag = peekTag(buf);
  189.       switch (tag)
  190.     { case DT_IDAuthentication:
  191.         buf = readString(&auth,buf);
  192.         break;
  193.       case DT_ImplementationID:
  194.         buf = readString(&id,buf);
  195.         break;
  196.       case DT_ImplementationName:
  197.         buf = readString(&name,buf);
  198.         break;
  199.       case DT_ImplementationVersion:
  200.         buf = readString(&version,buf);
  201.         break;
  202.       case DT_ReferenceID:
  203.         buf = readAny(&refID,buf);
  204.         break;
  205.       default:
  206.         freeBitMap(versionBM);
  207.         freeBitMap(optionsBM);
  208.         s_free(auth);
  209.         s_free(id);
  210.         s_free(name);
  211.         s_free(version);
  212.         freeAny(refID);
  213.         REPORT_READ_ERROR(buf);
  214.         break;
  215.       }
  216.     }
  217.  
  218.   buf = readInitInfo(&userInfo,buf);
  219.   if (buf == NULL)
  220.     { freeBitMap(versionBM);
  221.       freeBitMap(optionsBM);
  222.       s_free(auth);
  223.       s_free(id);
  224.       s_free(name);
  225.       s_free(version);
  226.       freeAny(refID);
  227.     }
  228.   RETURN_ON_NULL(buf);
  229.  
  230.   /* construct the basic init object */
  231.   *init = makeInitAPDU(search,present,delete,accessControl,resourceControl,
  232.                        prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  233.                           
  234.   freeBitMap(versionBM);
  235.   freeBitMap(optionsBM);
  236.   s_free(auth);
  237.   s_free(id);
  238.   s_free(name);
  239.   s_free(version);
  240.   freeAny(refID);
  241.   
  242.   return(buf);
  243. }
  244.  
  245. /*----------------------------------------------------------------------*/
  246.  
  247. InitResponseAPDU* 
  248. makeInitResponseAPDU(result,
  249.              search,
  250.              present,
  251.              deleteIt,
  252.              accessControl,
  253.              resourceControl,
  254.              prefSize,
  255.              maxMsgSize,
  256.              auth,
  257.              id,
  258.              name,
  259.              version,
  260.              refID,
  261.              userInfo)
  262. boolean result;
  263. boolean search;
  264. boolean present;
  265. boolean deleteIt;
  266. boolean accessControl;
  267. boolean resourceControl;
  268. long prefSize;
  269. long maxMsgSize;
  270. char* auth;
  271. char* id;
  272. char* name;
  273. char* version;
  274. any* refID;
  275. void* userInfo;
  276. /* build an initResponse APDU with user specified information */
  277.   InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((size_t)sizeof(InitResponseAPDU));
  278.  
  279.   init->PDUType = initResponseAPDU;
  280.   init->Result = result;
  281.   init->willSearch = search;
  282.   init->willPresent = present;
  283.   init->willDelete = deleteIt;
  284.   init->supportAccessControl = accessControl;
  285.   init->supportResourceControl = resourceControl;
  286.   init->PreferredMessageSize = prefSize;
  287.   init->MaximumRecordSize = maxMsgSize;
  288.   init->IDAuthentication = s_strdup(auth);
  289.   init->ImplementationID = s_strdup(id);
  290.   init->ImplementationName = s_strdup(name);
  291.   init->ImplementationVersion = s_strdup(version);
  292.   init->ReferenceID = duplicateAny(refID);
  293.   init->UserInformationField = userInfo; /* not copied! */
  294.   
  295.   return(init);
  296. }
  297.  
  298. /*----------------------------------------------------------------------*/
  299.  
  300. void 
  301. freeInitResponseAPDU(init)
  302. InitResponseAPDU* init;
  303. /* free an initAPDU */
  304. {
  305.   s_free(init->IDAuthentication);
  306.   s_free(init->ImplementationID);
  307.   s_free(init->ImplementationName);
  308.   s_free(init->ImplementationVersion);
  309.   freeAny(init->ReferenceID);
  310.   s_free(init);
  311. }
  312.  
  313. /*----------------------------------------------------------------------*/
  314.  
  315. char* 
  316. writeInitResponseAPDU(init,buffer,len)
  317. InitResponseAPDU* init;
  318. char* buffer;
  319. long* len;
  320. /* write the initResponse to a buffer, adding system information */
  321.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  322.   long size;
  323.   bit_map* optionsBM = NULL;
  324.  
  325.   RESERVE_SPACE_FOR_HEADER(len);
  326.   
  327.   buf = writePDUType(init->PDUType,buf,len);
  328.   buf = writeBoolean(init->Result,buf,len);
  329.   buf = writeProtocolVersion(buf,len);
  330.   
  331.   optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
  332.                          init->willDelete,init->supportAccessControl,
  333.                          init->supportResourceControl);
  334.   buf = writeBitMap(optionsBM,DT_Options,buf,len);
  335.   freeBitMap(optionsBM);
  336.  
  337.   buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
  338.   buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
  339.   buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
  340.   buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
  341.   buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
  342.   buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
  343.   buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
  344.   
  345.   /* go back and write the header-length-indicator */
  346.   RELEASE_HEADER_SPACE(len);
  347.   size = buf - buffer - HEADER_LEN; 
  348.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  349.  
  350.   if (init->UserInformationField != NULL)
  351.     buf = writeInitResponseInfo(init,buf,len);   
  352.     
  353.   return(buf);
  354. }
  355.  
  356. /*----------------------------------------------------------------------*/
  357.  
  358. char* 
  359. readInitResponseAPDU(init,buffer)
  360. InitResponseAPDU** init;
  361. char* buffer;
  362. {
  363.   char* buf = buffer;
  364.   boolean search,present,delete,accessControl,resourceControl;
  365.   long prefSize,maxMsgSize;
  366.   char *auth,*id,*name,*version;
  367.   long size; 
  368.   pdu_type pduType;
  369.   bit_map* versionBM = NULL;
  370.   bit_map* optionsBM = NULL;
  371.   boolean result;
  372.   any *refID = NULL;
  373.   void* userInfo = NULL;
  374.   
  375.   auth = id = name = version = NULL;
  376.   refID = NULL;
  377.   
  378.   /* read required part */
  379.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  380.   buf = readPDUType(&pduType,buf);
  381.   buf = readBoolean(&result,buf);
  382.   buf = readBitMap(&versionBM,buf); 
  383.   buf = readBitMap(&optionsBM,buf);
  384.   buf = readNum(&prefSize,buf);
  385.   buf = readNum(&maxMsgSize,buf);
  386.   
  387.   /* decode optionsBM */
  388.   search = bitAtPos(0L,optionsBM);
  389.   present = bitAtPos(1L,optionsBM);
  390.   delete = bitAtPos(2L,optionsBM);
  391.   accessControl = bitAtPos(3L,optionsBM);
  392.   resourceControl = bitAtPos(4L,optionsBM);
  393.   
  394.   /* read optional part */
  395.   while (buf < (buffer + size + HEADER_LEN)) 
  396.     { data_tag tag = peekTag(buf);
  397.       switch (tag)
  398.     { case DT_IDAuthentication:
  399.         buf = readString(&auth,buf);
  400.         break;
  401.       case DT_ImplementationID:
  402.         buf = readString(&id,buf);
  403.         break;
  404.       case DT_ImplementationName:
  405.         buf = readString(&name,buf);
  406.         break;
  407.       case DT_ImplementationVersion:
  408.         buf = readString(&version,buf);
  409.         break;
  410.       case DT_ReferenceID:
  411.         buf = readAny(&refID,buf);
  412.         break;
  413.       default:
  414.         freeBitMap(versionBM);
  415.         freeBitMap(optionsBM);
  416.         s_free(auth);
  417.         s_free(id);
  418.         s_free(name);
  419.         s_free(version);
  420.         freeAny(refID);
  421.         REPORT_READ_ERROR(buf);
  422.         break;
  423.       }
  424.     }
  425.  
  426.   buf = readInitResponseInfo(&userInfo,buf);
  427.   if (buf == NULL)
  428.     { freeBitMap(versionBM);
  429.       freeBitMap(optionsBM);
  430.       s_free(auth);
  431.       s_free(id);
  432.       s_free(name);
  433.       s_free(version);
  434.       freeAny(refID);
  435.     }
  436.   RETURN_ON_NULL(buf);
  437.   
  438.   /* construct the basic init object */
  439.   *init = makeInitResponseAPDU(result,
  440.                    search,present,delete,accessControl,resourceControl,
  441.                    prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
  442.                                           
  443.   freeBitMap(versionBM);
  444.   freeBitMap(optionsBM);
  445.   s_free(auth);
  446.   s_free(id);
  447.   s_free(name);
  448.   s_free(version);
  449.   freeAny(refID);
  450.   
  451.   return(buf);
  452. }
  453.  
  454. /*----------------------------------------------------------------------*/
  455.  
  456. InitResponseAPDU* 
  457. replyToInitAPDU(init,result,userInfo)
  458. InitAPDU* init;
  459. boolean result;
  460. void* userInfo;
  461. /* respond to an init message in the default way - echoing back
  462.    the init info 
  463.  */
  464. {
  465.   InitResponseAPDU* initResp;
  466.   initResp = makeInitResponseAPDU(result,
  467.                   init->willSearch,init->willPresent,init->willDelete,
  468.                   init->supportAccessControl,init->supportResourceControl,
  469.                   init->PreferredMessageSize,init->MaximumRecordSize,
  470.                   init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
  471.                   defaultImplementationVersion(),
  472.                   init->ReferenceID,userInfo);
  473.   return(initResp);
  474. }
  475.  
  476. /*----------------------------------------------------------------------*/
  477.  
  478. SearchAPDU* 
  479. makeSearchAPDU(small,
  480.            large,
  481.            medium,
  482.            replace,
  483.            name,
  484.            databases,
  485.            type,
  486.            elements,
  487.            refID,
  488.            queryInfo)
  489. long small;
  490. long large;
  491. long medium;
  492. boolean replace;
  493. char* name;
  494. char** databases;
  495. char* type;
  496. char** elements;
  497. any* refID;
  498. void* queryInfo;
  499. {
  500.   char* ptr = NULL;
  501.   long i;
  502.   SearchAPDU* query = (SearchAPDU*)s_malloc((size_t)sizeof(SearchAPDU));
  503.   query->PDUType = searchAPDU;
  504.   query->SmallSetUpperBound = small;
  505.   query->LargeSetLowerBound = large;
  506.   query->MediumSetPresentNumber = medium;
  507.   query->ReplaceIndicator = replace;
  508.   query->ResultSetName = s_strdup(name);
  509.   query->DatabaseNames = NULL; 
  510.   if (databases != NULL)
  511.     { for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
  512.     { if (query->DatabaseNames == NULL)
  513.         query->DatabaseNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  514.         else
  515.           query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
  516.                            (size_t)(sizeof(char*) * (i + 2)));
  517.         query->DatabaseNames[i] = s_strdup(ptr);
  518.         query->DatabaseNames[i+1] = NULL;
  519.       }
  520.       }
  521.   query->QueryType = s_strdup(type);
  522.   query->ElementSetNames = NULL; 
  523.   if (elements != NULL)
  524.     { for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
  525.     { if (query->ElementSetNames == NULL)
  526.         query->ElementSetNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  527.         else
  528.           query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
  529.                              (size_t)(sizeof(char*) * (i + 2)));
  530.         query->ElementSetNames[i] = s_strdup(ptr);
  531.         query->ElementSetNames[i+1] = NULL;
  532.       }
  533.       }
  534.   query->ReferenceID = duplicateAny(refID);
  535.   query->Query = queryInfo;    /* not copied! */
  536.   return(query);
  537. }
  538.  
  539. /*----------------------------------------------------------------------*/
  540.  
  541. void 
  542. freeSearchAPDU(query)
  543. SearchAPDU* query;
  544. {
  545.   s_free(query->ResultSetName);
  546.   s_free(query->QueryType);
  547.   doList((void**)query->DatabaseNames,fs_free); /* can't use the macro here ! */
  548.   s_free(query->DatabaseNames);
  549.   doList((void**)query->ElementSetNames,fs_free); /* can't use the macro here ! */
  550.   s_free(query->ElementSetNames);
  551.   freeAny(query->ReferenceID);
  552.   s_free(query);
  553. }
  554.  
  555. /*----------------------------------------------------------------------*/
  556.  
  557. #define DB_DELIMITER     "\037"     /* hex 1F occurs between each database name */
  558. #define ES_DELIMITER_1     "\037"     /* separates database name from element name */
  559. #define ES_DELIMITER_2     "\036"     /* hex 1E separates <db,es> groups from one another */
  560.  
  561. char* 
  562. writeSearchAPDU(query,buffer,len)
  563. SearchAPDU* query;
  564. char* buffer;
  565. long* len;
  566.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  567.   long size,i;
  568.   char* ptr = NULL;
  569.   char* scratch = NULL;
  570.  
  571.   RESERVE_SPACE_FOR_HEADER(len);
  572.   
  573.   buf = writePDUType(query->PDUType,buf,len);
  574.   buf = writeBinaryInteger(query->SmallSetUpperBound,(size_t)3,buf,len);
  575.   buf = writeBinaryInteger(query->LargeSetLowerBound,(size_t)3,buf,len);
  576.   buf = writeBinaryInteger(query->MediumSetPresentNumber,(size_t)3,buf,len);
  577.   buf = writeBoolean(query->ReplaceIndicator,buf,len);
  578.   buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
  579.   /* write database names */
  580.   if (query->DatabaseNames != NULL)
  581.     { for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
  582.     { if (scratch == NULL)
  583.         scratch = s_strdup(ptr);
  584.         else
  585.       { size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + 3);
  586.         scratch = (char*)s_realloc(scratch,newScratchSize);
  587.         s_strncat(scratch,DB_DELIMITER,2L,newScratchSize);
  588.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
  589.       }
  590.       }
  591.     buf = writeString(scratch,DT_DatabaseNames,buf,len);
  592.     s_free(scratch);
  593.       }
  594.   buf = writeString(query->QueryType,DT_QueryType,buf,len);
  595.   /* write element set names */
  596.   if (query->ElementSetNames != NULL)
  597.     { for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
  598.     { if (scratch == NULL)
  599.         { if (query->ElementSetNames[i+1] == NULL) /* there is a single element set name */
  600.         { scratch = (char*)s_malloc((size_t)strlen(ptr) + 3);
  601.           strncpy(scratch,ES_DELIMITER_1,2);
  602.           s_strncat(scratch,ptr,strlen(ptr) + 1,strlen(ptr) + 2);
  603.         }
  604.         else        /* this is the first of a series of element set names */
  605.           { size_t newScratchSize = (size_t)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 3);
  606.         scratch = s_strdup(ptr); /* the database name */
  607.         ptr = query->ElementSetNames[++i]; /* the element set name */
  608.         scratch = (char*)s_realloc(scratch,newScratchSize);
  609.         s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  610.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize); 
  611.           }
  612.           }
  613.         else
  614.       { char* esPtr = query->ElementSetNames[++i]; /* the element set name */
  615.         size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
  616.         scratch = (char*)s_realloc(scratch,newScratchSize);
  617.         s_strncat(scratch,ES_DELIMITER_2,2L,newScratchSize);
  618.         s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
  619.         s_strncat(scratch,ES_DELIMITER_1,2L,newScratchSize);
  620.         s_strncat(scratch,esPtr,strlen(esPtr) + 1,newScratchSize); 
  621.       }
  622.       }
  623.     buf = writeString(scratch,DT_ElementSetNames,buf,len);
  624.     s_free(scratch);
  625.       }                        
  626.   buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
  627.     
  628.   /* go back and write the header-length-indicator */
  629.   RELEASE_HEADER_SPACE(len);
  630.   size = buf - buffer - HEADER_LEN; 
  631.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  632.  
  633.   if (query->Query != NULL)
  634.     buf = writeSearchInfo(query,buf,len);    
  635.     
  636.   return(buf);
  637. }
  638.  
  639. /*----------------------------------------------------------------------*/
  640.  
  641. char*
  642. readSearchAPDU(query,buffer)
  643. SearchAPDU** query;
  644. char* buffer;
  645. {
  646.   char* buf = buffer;
  647.   long size;
  648.   pdu_type pduType;
  649.   long small,large,medium,numItems;
  650.   boolean replace;
  651.   char *name,*databaseNames,*type,*elements;
  652.   char **dbList,**elemList;
  653.   any *refID;
  654.   void* userInfo = NULL;
  655.   
  656.   name = databaseNames = type = elements = NULL;
  657.   dbList = elemList = NULL;
  658.   refID = NULL;
  659.  
  660.   /* read required part */
  661.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  662.   buf = readPDUType(&pduType,buf);
  663.   buf = readBinaryInteger(&small,(size_t)3,buf);
  664.   buf = readBinaryInteger(&large,(size_t)3,buf);
  665.   buf = readBinaryInteger(&medium,(size_t)3,buf);
  666.   buf = readBoolean(&replace,buf);
  667.   
  668.   /* read optional part */
  669.   while (buf < (buffer + size + HEADER_LEN)) 
  670.     { data_tag tag = peekTag(buf);
  671.       switch (tag)
  672.     { case DT_ResultSetName:
  673.         buf = readString(&name,buf);
  674.         break;
  675.       case DT_DatabaseNames:
  676.         {            /* parse the database names */
  677.           char *tok;
  678.           buf = readString(&databaseNames,buf);
  679.           tok = strtok(databaseNames,DB_DELIMITER);
  680.           numItems = 0;
  681.           while (tok != NULL)
  682.         { if (dbList == NULL)
  683.             dbList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  684.         else
  685.           dbList = (char**)s_realloc((char*)dbList,(size_t)(sizeof(char*) * (numItems+2)));
  686.             dbList[numItems++] = s_strdup(tok);
  687.             dbList[numItems] = NULL;
  688.             tok = strtok(NULL,DB_DELIMITER);
  689.           }
  690.         }
  691.         break;
  692.       case DT_QueryType:
  693.         buf = readString(&type,buf);
  694.         break;
  695.       case DT_ElementSetNames:
  696.         {            /* parse the element set names */
  697.           char *tok;
  698.           buf = readString(&elements,buf);
  699.           if (elements[0] == ES_DELIMITER_1[0]) /* this is a single element w/ no db */
  700.         { elemList = (char**)s_malloc((size_t)(sizeof(char*) * 2));
  701.           elemList[0] = s_strdup(elements);
  702.           elemList[1] = NULL;
  703.         }
  704.           else        /* its a group of <DB/ES> pairs */
  705.         { char* esTok = NULL;
  706.           tok = strtok(elements,ES_DELIMITER_1); /* db name */
  707.           esTok = strtok(NULL,ES_DELIMITER_2); /* es name */
  708.           numItems = 0;
  709.           while (tok != NULL)
  710.             { if (elemList == NULL)
  711.             elemList = (char**)s_malloc((size_t)(sizeof(char*) * 3));
  712.             else
  713.               elemList = (char**)s_realloc((char*)elemList,(size_t)(sizeof(char*) * (numItems * 2 + 1)));
  714.             elemList[numItems++] = s_strdup(tok);
  715.             elemList[numItems++] = s_strdup(esTok);
  716.             elemList[numItems] = NULL;
  717.             tok = strtok(NULL,ES_DELIMITER_1);
  718.             esTok = strtok(NULL,ES_DELIMITER_2);
  719.               } 
  720.         }
  721.         }
  722.         break;
  723.       case DT_ReferenceID:
  724.         buf = readAny(&refID,buf);
  725.         break;
  726.       default:
  727.         s_free(name);
  728.         s_free(type);
  729.         s_free(databaseNames);
  730.         doList((void**)dbList,fs_free);
  731.         s_free(dbList);
  732.         s_free(elements);
  733.         doList((void**)elemList,fs_free);
  734.         s_free(elemList);
  735.         freeAny(refID);
  736.         REPORT_READ_ERROR(buf);
  737.         break;
  738.       }
  739.     }
  740.   
  741.   buf = readSearchInfo(&userInfo,buf);
  742.   if (buf == NULL)
  743.     { s_free(name);
  744.       s_free(type);
  745.       s_free(databaseNames);
  746.       doList((void**)dbList,fs_free);
  747.       s_free(dbList);
  748.       s_free(elements);
  749.       doList((void**)elemList,fs_free);
  750.       s_free(elemList);
  751.       freeAny(refID);
  752.     }
  753.   RETURN_ON_NULL(buf);
  754.     
  755.   /* construct the search object */
  756.   *query = makeSearchAPDU(small,large,medium,replace,name,dbList,type,elemList,refID,userInfo);
  757.  
  758.   s_free(name);
  759.   s_free(type);
  760.   s_free(databaseNames);
  761.   doList((void**)dbList,fs_free);
  762.   s_free(dbList);
  763.   s_free(elements);
  764.   doList((void**)elemList,fs_free);
  765.   s_free(elemList);
  766.   freeAny(refID);
  767.   
  768.   return(buf);
  769. }
  770.  
  771. /*----------------------------------------------------------------------*/
  772.  
  773. SearchResponseAPDU* 
  774. makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
  775.                presentStatus,refID,records)
  776. long result;
  777. long count;
  778. long recordsReturned;
  779. long nextPos;
  780. long resultStatus;
  781. long presentStatus;
  782. any* refID;
  783. void* records;
  784. {
  785.   SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((size_t)sizeof(SearchResponseAPDU));
  786.   query->PDUType = searchResponseAPDU;
  787.   query->SearchStatus = result;
  788.   query->ResultCount = count;
  789.   query->NumberOfRecordsReturned = recordsReturned;
  790.   query->NextResultSetPosition = nextPos;
  791.   query->ResultSetStatus = resultStatus;
  792.   query->PresentStatus = presentStatus;
  793.   query->ReferenceID = duplicateAny(refID);
  794.   query->DatabaseDiagnosticRecords = records;
  795.   return(query);  
  796. }
  797.  
  798. /*----------------------------------------------------------------------*/
  799.  
  800. void 
  801. freeSearchResponseAPDU(queryResponse)
  802. SearchResponseAPDU* queryResponse;
  803. {
  804.   freeAny(queryResponse->ReferenceID);
  805.   s_free(queryResponse);
  806. }
  807.  
  808. /*----------------------------------------------------------------------*/
  809.  
  810. char* 
  811. writeSearchResponseAPDU(queryResponse,buffer,len)
  812. SearchResponseAPDU* queryResponse;
  813. char* buffer;
  814. long* len;
  815. {
  816.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  817.   long size;
  818.  
  819.   RESERVE_SPACE_FOR_HEADER(len);
  820.   
  821.   buf = writePDUType(queryResponse->PDUType,buf,len);
  822.   buf = writeBinaryInteger(queryResponse->SearchStatus,(size_t)1,buf,len);
  823.   buf = writeBinaryInteger(queryResponse->ResultCount,(size_t)3,buf,len);
  824.   buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,(size_t)3,buf,len);
  825.   buf = writeBinaryInteger(queryResponse->NextResultSetPosition,(size_t)3,buf,len);
  826.   buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
  827.   buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
  828.   buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
  829.     
  830.   /* go back and write the header-length-indicator */
  831.   RELEASE_HEADER_SPACE(len);
  832.   size = buf - buffer - HEADER_LEN; 
  833.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  834.  
  835.   if (queryResponse->DatabaseDiagnosticRecords != NULL)
  836.     buf = writeSearchResponseInfo(queryResponse,buf,len);    
  837.     
  838.   return(buf);
  839. }
  840.  
  841. /*----------------------------------------------------------------------*/
  842.  
  843. char* 
  844. readSearchResponseAPDU(queryResponse,buffer)
  845. SearchResponseAPDU** queryResponse;
  846. char* buffer;
  847. {
  848.   char* buf = buffer;
  849.   long size;
  850.   pdu_type pduType;
  851.   long result,count,recordsReturned,nextPos;
  852.   long resultStatus,presentStatus;
  853.   any *refID = NULL;
  854.   void* userInfo = NULL;
  855.   
  856.   /* read required part */
  857.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  858.   buf = readPDUType(&pduType,buf);
  859.   buf = readBinaryInteger(&result,(size_t)1,buf);
  860.   buf = readBinaryInteger(&count,(size_t)3,buf);
  861.   buf = readBinaryInteger(&recordsReturned,(size_t)3,buf);
  862.   buf = readBinaryInteger(&nextPos,(size_t)3,buf);
  863.   
  864.   resultStatus = presentStatus = UNUSED;
  865.   refID = NULL;
  866.  
  867.   /* read optional part */
  868.   while (buf < (buffer + size + HEADER_LEN)) 
  869.     { data_tag tag = peekTag(buf);
  870.       switch (tag)
  871.     { case DT_ResultSetStatus:
  872.         buf = readNum(&resultStatus,buf);
  873.         break;
  874.       case DT_PresentStatus:
  875.         buf = readNum(&presentStatus,buf);
  876.         break;
  877.       case DT_ReferenceID:
  878.         buf = readAny(&refID,buf);
  879.         break;
  880.       default:
  881.         freeAny(refID);
  882.         REPORT_READ_ERROR(buf);
  883.         break;
  884.       }
  885.     }
  886.   
  887.   buf = readSearchResponseInfo(&userInfo,buf);
  888.   if (buf == NULL)
  889.     freeAny(refID);
  890.   RETURN_ON_NULL(buf);
  891.   
  892.   /* construct the search object */
  893.   *queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
  894.                       (long)resultStatus,(long)presentStatus,refID,userInfo);
  895.  
  896.   freeAny(refID);
  897.   
  898.   return(buf);
  899. }
  900.  
  901. #ifdef NOTUSED
  902. /*----------------------------------------------------------------------*/
  903.  
  904.  
  905. PresentAPDU* 
  906. makePresentAPDU(recsReq,startPos,resultID,refID,info)
  907. long recsReq;
  908. long startPos;
  909. char* resultID;
  910. any* refID;
  911. void* info;
  912. {
  913.   PresentAPDU* present = (PresentAPDU*)s_malloc((size_t)sizeof(PresentAPDU));
  914.   present->PDUType = presentAPDU;
  915.   present->NumberOfRecordsRequested = recsReq;
  916.   present->ResultSetStartPosition = startPos;
  917.   present->ResultSetID = s_strdup(resultID);
  918.   present->ElementSetNames = NULL; /* XXX for now */
  919.   present->ReferenceID = duplicateAny(refID);
  920.   present->PresentInfo = info;
  921.   return(present);  
  922. }
  923.  
  924. /*----------------------------------------------------------------------*/
  925.  
  926. void 
  927. freePresentAPDU(present)
  928. PresentAPDU* present;
  929. {
  930.   /* handle element set names */ 
  931.   s_free(present->ResultSetID);
  932.   freeAny(present->ReferenceID);
  933.   s_free(present);
  934. }
  935.  
  936. /*----------------------------------------------------------------------*/
  937.  
  938. char* 
  939. writePresentAPDU(present,buffer,len)
  940. PresentAPDU* present;
  941. char* buffer;
  942. long* len;
  943. {
  944.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  945.   long size;
  946.  
  947.   RESERVE_SPACE_FOR_HEADER(len);
  948.   
  949.   buf = writePDUType(present->PDUType,buf,len);
  950.   buf = writeBinaryInteger(present->NumberOfRecordsRequested,(size_t)3,buf,len);
  951.   buf = writeBinaryInteger(present->ResultSetStartPosition,(size_t)3,buf,len);
  952.   buf = writeString(present->ResultSetID,DT_ResultSetID,buf,len); 
  953.   /* handle element set names */
  954.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  955.     
  956.   /* go back and write the header-length-indicator */
  957.   RELEASE_HEADER_SPACE(len);
  958.   size = buf - buffer - HEADER_LEN; 
  959.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  960.  
  961.   if (present->PresentInfo != NULL)
  962.     buf = writePresentInfo(present,buf,len);   
  963.     
  964.   return(buf); 
  965. }
  966.  
  967. /*----------------------------------------------------------------------*/
  968.  
  969. char* 
  970. readPresentAPDU(present,buffer)
  971. PresentAPDU** present;
  972. char* buffer;
  973. {
  974.   char* buf = buffer;
  975.   long size;
  976.   pdu_type pduType;
  977.   long recsReq,startPos;
  978.   char* resultID = NULL;
  979.   any *refID = NULL;
  980.   void* userInfo = NULL;
  981.   
  982.   /* read required part */
  983.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  984.   buf = readPDUType(&pduType,buf);
  985.   buf = readBinaryInteger(&recsReq,(size_t)3,buf);
  986.   buf = readBinaryInteger(&startPos,(size_t)3,buf);
  987.   buf = readString(&resultID,buf);
  988.   
  989.   /* read optional part */
  990.   while (buf < (buffer + size + HEADER_LEN)) 
  991.    { data_tag tag = peekTag(buf);
  992.      switch (tag)
  993.       { case DT_ReferenceID:
  994.           buf = readAny(&refID,buf);
  995.           break;
  996.         default:
  997.           s_free(resultID);
  998.           freeAny(refID);
  999.           REPORT_READ_ERROR(buf);
  1000.           break;
  1001.       }
  1002.    }
  1003.   
  1004.   buf = readPresentInfo(&userInfo,buf);
  1005.   if (buf == NULL)
  1006.    { s_free(resultID);
  1007.      freeAny(refID);
  1008.    }
  1009.   RETURN_ON_NULL(buf);
  1010.  
  1011.   /* construct the present object */
  1012.   *present = makePresentAPDU(recsReq,startPos,resultID,refID,userInfo);
  1013.  
  1014.   s_free(resultID);
  1015.   freeAny(refID);
  1016.   
  1017.   return(buf);
  1018. }
  1019.  
  1020. /*----------------------------------------------------------------------*/
  1021.  
  1022.  
  1023. PresentResponseAPDU* 
  1024. makePresentResponseAPDU(status,recsRet,nextPos,refID,records)
  1025. boolean status;
  1026. long recsRet;
  1027. long nextPos;
  1028. any* refID;
  1029. void* records;
  1030. {
  1031.   PresentResponseAPDU* present = (PresentResponseAPDU*)s_malloc((size_t)sizeof(PresentResponseAPDU));
  1032.   present->PDUType = presentResponseAPDU;
  1033.   present->PresentStatus = status;
  1034.   present->NumberOfRecordsReturned = recsRet;
  1035.   present->NextResultSetPosition = nextPos;
  1036.   present->ReferenceID = duplicateAny(refID);
  1037.   present->DatabaseDiagnosticRecords = records;
  1038.   return(present);  
  1039. }
  1040.  
  1041. /*----------------------------------------------------------------------*/
  1042.  
  1043. void 
  1044. freePresentResponseAPDU(present)
  1045. PresentResponseAPDU* present;
  1046.   freeAny(present->ReferenceID);
  1047.   s_free(present);
  1048. }
  1049.  
  1050. /*----------------------------------------------------------------------*/
  1051.  
  1052. char* 
  1053. writePresentResponseAPDU(present,buffer,len)
  1054. PresentResponseAPDU* present;
  1055. char* buffer;
  1056. long* len;
  1057. {
  1058.   char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
  1059.   long size;
  1060.  
  1061.   RESERVE_SPACE_FOR_HEADER(len);
  1062.   
  1063.   buf = writePDUType(present->PDUType,buf,len);
  1064.   buf = writeBoolean(present->PresentStatus,buf,len);
  1065.   buf = writeBinaryInteger(present->NumberOfRecordsReturned,(size_t)3,buf,len);
  1066.   buf = writeBinaryInteger(present->NextResultSetPosition,(size_t)3,buf,len);
  1067.   buf = writeAny(present->ReferenceID,DT_ReferenceID,buf,len);
  1068.     
  1069.   /* go back and write the header-length-indicator */
  1070.   RELEASE_HEADER_SPACE(len);
  1071.   size = buf - buffer - HEADER_LEN; 
  1072.   writeBinaryInteger(size,HEADER_LEN,buffer,len);
  1073.  
  1074.   if (present->DatabaseDiagnosticRecords != NULL)
  1075.     buf = writePresentResponseInfo(present,buf,len);
  1076.     
  1077.   return(buf);
  1078. }
  1079.  
  1080. /*----------------------------------------------------------------------*/
  1081.  
  1082. char* 
  1083. readPresentResponseAPDU(present,buffer)
  1084. PresentResponseAPDU** present;
  1085. char* buffer;
  1086. {
  1087.   char* buf = buffer;
  1088.   long size;
  1089.   pdu_type pduType;
  1090.   boolean status;
  1091.   long recsRet,nextPos;
  1092.   any *refID = NULL;
  1093.   void* userInfo = NULL;
  1094.  
  1095.   /* read required part */
  1096.   buf = readBinaryInteger(&size,HEADER_LEN,buf); 
  1097.   buf = readPDUType(&pduType,buf);
  1098.   buf = readBoolean(&status,buf);
  1099.   buf = readBinaryInteger(&recsRet,(size_t)3,buf);
  1100.   buf = readBinaryInteger(&nextPos,(size_t)3,buf);
  1101.  
  1102.   /* read optional part */
  1103.   while (buf < (buffer + size + HEADER_LEN)) 
  1104.    { data_tag tag = peekTag(buf);
  1105.      switch (tag)
  1106.       { case DT_ReferenceID:
  1107.           buf = readAny(&refID,buf);
  1108.           break;
  1109.         default:
  1110.           freeAny(refID);
  1111.           REPORT_READ_ERROR(buf);
  1112.           break;
  1113.       }
  1114.    }
  1115.   
  1116.   buf = readPresentResponseInfo(&userInfo,buf);
  1117.   if (buf == NULL)
  1118.     freeAny(refID);
  1119.   RETURN_ON_NULL(buf);
  1120.  
  1121.   /* construct the presentResponse object */
  1122.   *present = makePresentResponseAPDU(status,recsRet,nextPos,refID,userInfo);
  1123.  
  1124.   freeAny(refID);
  1125.   
  1126.   return(buf);
  1127. }
  1128.  
  1129. /*----------------------------------------------------------------------*/
  1130.  
  1131.  
  1132. #endif /* def NOTUSED */
  1133.